import { platformInfo } from "../../shared/api_bot/IBody";
import player from "../rpg/entity/player";
import sdk from "../index";
import Counter, { CounterKey } from "./Counter";
import { ComType } from "../tool/component";
import client_component from "../../component/client_component";
import MailManage from "./MailManage";
import { BaseBody } from "../rpg/entity/body_base";
import base_component from "../../component/base_component";
import rpg_component from "../../component/rpg_component";
import pos_component from "../../component/pos_component";
import bag_component from "../../component/bag_component";
import equip_component from "../../component/equip_component";
import intent_component from "../../component/intent_component";

import pop_component from "../../component/pop_component";
import follow_component from "../../component/follow_component";
import create_component from "../../component/create_component";
import talent_component from "../../component/talent_component";
import mail_component from "../../component/mail_component";
import admin_component from "../../component/admin_component";
import dieReward_component from "../../component/dieReward_component";
import task_component from "../../component/task_component";
import { BaseManager } from "./BaseManager";

// 用户名字记录接口
interface UserNameRecord {
    _id?: string;
    uid: string;           // 用户ID
    name: string;          // 用户名字
    level?: number;        // 用户等级（未来扩展）
    createTime: number;    // 创建时间
    updateTime: number;    // 更新时间
}

const cron = require('node-cron');

// 配置常量
const OFFLINE_CHECK_INTERVAL = '*/5 * * * *'; // 5分钟检查一次
const OFFLINE_TIMEOUT = 5 * 60 * 1000; // 5分钟超时
const MAX_ONLINE_PLAYERS = 10000; // 最大在线玩家数

interface GateRecord {
    key: string;
    val: string;
}

interface PlayerData {
    id: string;
    [key: string]: any;
}

class UserManager extends BaseManager {
    private userMap = new Map<string, player>();
    private gateMap: Map<string, string> = new Map();
    private nameMap: Map<string, string> = new Map(); // name -> uid 的映射
    private offlineCheckTask?: any;

    constructor() {
        super();
        // UserManager依赖Counter和MailManage
        this.dependencies = ['Counter', 'MailManage'];
    }

    /**
     * 初始化用户管理器
     */
    async init(): Promise<void> {
        if (this.isInitialized) {
            this.log('warn', '已经初始化过了');
            return;
        }

        try {
            await this.loadGateData();
            await this.loadNameData();
            this.startOfflineCheck();
            this.markAsInitialized();
        } catch (error) {
            this.handleError(error, 'UserManager初始化');
        }
    }

    /**
     * 加载门禁数据
     */
    private async loadGateData(): Promise<void> {
        try {
            const data = (await sdk.db.find('gate')) as unknown as GateRecord[];
            data.forEach(record => {
                this.gateMap.set(record.key, record.val);
            });
            console.log(`加载了 ${data.length} 条门禁数据`);
        } catch (error) {
            console.error('加载门禁数据失败:', error);
            throw error;
        }
    }

    /**
     * 加载名字数据到内存
     */
    private async loadNameData(): Promise<void> {
        try {
            const data = await sdk.db.find('user_names') as unknown as UserNameRecord[];
            data.forEach(record => {
                this.nameMap.set(record.name, record.uid);
            });
            console.log(`加载了 ${data.length} 条用户名数据`);
        } catch (error) {
            console.error('加载用户名数据失败:', error);
            throw error;
        }
    }

    /**
     * 启动离线检查任务
     */
    private startOfflineCheck(): void {
        this.offlineCheckTask = cron.schedule(OFFLINE_CHECK_INTERVAL, () => {
            this.checkOfflineUsers();
        });
        console.log('离线检查任务已启动');
    }

    /**
     * 检查离线用户
     */
    private checkOfflineUsers(): void {
        if (this.userMap.size === 0) {
            return;
        }

        const now = Date.now();
        const offlineUsers: string[] = [];

        // 使用 for...of 替代 forEach 以提高性能
        for (const [uid, user] of this.userMap) {
            try {
                const com = user.getComponent(ComType.client) as client_component;
                if (!com) {
                    console.warn(`玩家 ${uid} 缺少客户端组件`);
                    offlineUsers.push(uid);
                    continue;
                }

                const isOffline = now - com.lastActiveTime > OFFLINE_TIMEOUT;
                if (isOffline) {
                    offlineUsers.push(uid);
                }
            } catch (error) {
                console.error(`检查玩家 ${uid} 状态时出错:`, error);
                offlineUsers.push(uid);
            }
        }

        // 批量处理离线用户
        if (offlineUsers.length > 0) {
            console.log(`发现 ${offlineUsers.length} 个离线用户`);
            this.handleOfflineUsers(offlineUsers);
        }
    }

    /**
     * 处理离线用户
     */
    private async handleOfflineUsers(offlineUserIds: string[]): Promise<void> {
        for (const uid of offlineUserIds) {
            try {
                const user = this.userMap.get(uid);
                if (user) {
                    let saveData = await user.save();
                    await sdk.db.update('player',{id:uid},saveData);
                    console.log(`玩家 ${uid} 已离线并保存数据`);
                }
                this.userMap.delete(uid);
            } catch (error) {
                console.error(`处理离线用户 ${uid} 时出错:`, error);
            }
        }
        console.log(`当前在线人数: ${this.userMap.size}`);
    }

    /**
     * 创建新玩家
     */
    async create(info: platformInfo): Promise<player> {
        if (this.userMap.size >= MAX_ONLINE_PLAYERS) {
            throw new Error('服务器已达到最大在线人数限制');
        }

        const existingUuid = this.getUuid(info);
        if (existingUuid) {
            let player =  await this.getPlayer(info);
            if(player){
                return player;
            }
        }

        const newPlayer = new player();
        newPlayer.id = Counter.get(CounterKey.玩家总数);
        
        this.addGateRecord(info, newPlayer.id, true);
        
        // 添加用户名记录（使用默认名字）
        // const defaultName = `玩家${newPlayer.id}`;
        // this.addUserName(newPlayer.id, defaultName);
        
        this.registerPlayer(newPlayer);
        newPlayer.register();
        
        console.log(`创建新玩家: ${newPlayer.id}`);
        return newPlayer;
    }

    /**
     * 注册玩家到在线列表
     */
    registerPlayer(p: player): void {
        if (!p || !p.id) {
            throw new Error('无效的玩家对象');
        }

        this.userMap.set(p.id, p);
        console.info(`玩家上线，当前在线人数: ${this.userMap.size}`);
    }

    /**
     * 添加门禁记录
     */
    private addGateRecord(info: platformInfo, uid: string, save: boolean = false): void {
        const gateKey = `${info.name}*${info.id}`;
        this.gateMap.set(gateKey, uid);
        
        if (save) {
            // 异步保存到数据库，但不等待
            sdk.db.insert('gate', { uid, platform: info }).catch(error => {
                console.error('保存门禁记录失败:', error);
                // 回滚内存中的记录
                this.gateMap.delete(gateKey);
            });
        }
    }

    /**
     * 获取平台账号对应的用户ID
     */
    getUuid(info: platformInfo): string | undefined {
        return this.gateMap.get(`${info.name}*${info.id}`);
    }


    /**
     * 获取所有在线玩家
     */
    getPlayers(): player[] {
        return Array.from(this.userMap.values());
    }
    getOnlinePlayer(id:string):player | undefined{
        return this.userMap.get(id);
    }
    /**
     * 获取在线玩家数量
     */
    getOnlineCount(): number {
        return this.userMap.size;
    }
  
    /**
     * 检查名字是否已被使用
     */
    isNameTaken(name: string): boolean {
        return this.nameMap.has(name);
    }
    /**
     * 根据UID 获取名字
     */
    getNameByUid(uid:string):string | undefined{
        // 遍历 nameMap 查找对应的名字
        for (const [name, nameUid] of this.nameMap) {
            if (nameUid === uid) {
                return name;
            }
        }
        return '匿名';
    }
    /**
     * 获取名字对应的用户ID
     */
    getUidByName(name: string): string | undefined {
        return this.nameMap.get(name);
    }

    /**
     * 检查名字是否可用
     */
    isNameAvailable(name: string): boolean {
        return !this.isNameTaken(name);
    }

    /**
     * 添加用户名记录
     */
    addUserName(uid: string, name: string, level: number = 1): void {
        if (this.isNameTaken(name)) {
            console.error(`名字 "${name}" 已被使用`);
            return;
        }

        // 只更新内存映射，不立即存储到数据库
        this.nameMap.set(name, uid);
        console.log(`添加用户名记录: ${name} -> ${uid}`);
    }

    /**
     * 更新用户名
     */
    updateUserName(uid: string, oldName: string, newName: string, level?: number): void {
        if (this.isNameTaken(newName)) {
            throw new Error(`名字 "${newName}" 已被使用`);
        }

        // 更新内存映射（立即生效）
        this.nameMap.delete(oldName);
        this.nameMap.set(newName, uid);

        console.log(`更新用户名: ${oldName} -> ${newName} (UID: ${uid})`);
    }

    /**
     * 更新玩家名字
     */
    updatePlayerName(uid: string, oldName: string, newName: string): void {
        this.updateUserName(uid, oldName, newName);
    }

    /**
     * 从数据库加载玩家
     */
    async loadPlayerFromDB(uid: string): Promise<player | undefined> {
        try {
            const data = await sdk.db.find('player', { id: uid }) as unknown as PlayerData[];
            if (data.length === 0) {
                return undefined;
            }

            const newPlayer = new player();
            newPlayer.load(data[0]);
            this.registerPlayer(newPlayer);
            return newPlayer;
        } catch (error) {
            console.error(`从数据库加载玩家 ${uid} 失败:`, error);
            return undefined;
        }
    }

    /**
     * 获取或创建玩家
     */
    async getPlayer(info: platformInfo): Promise<player | undefined> {
        try {
            // 首先尝试从本地获取
            const uuid = this.getUuid(info);
            if (uuid) {
                // 检查是否在线
                const onlinePlayer = this.userMap.get(uuid);
                if (onlinePlayer) {
                    return onlinePlayer;
                }
                
                // 从数据库加载
                return await this.loadPlayerFromDB(uuid);
            }

            // 从数据库查找绑定信息
            const bindInfo = await sdk.db.find('gate', { platform: info });
            if (bindInfo.length > 0) {
                const foundUuid = bindInfo[0].uid;
                this.gateMap.set(`${info.name}*${info.id}`, foundUuid);
                return await this.loadPlayerFromDB(foundUuid);
            }

            return undefined;
        } catch (error) {
            console.error('获取玩家信息失败:', error);
            return undefined;
        }
    }

    /**
     * 强制下线玩家
     */
    async forceOffline(uid: string): Promise<boolean> {
        const player = this.userMap.get(uid);
        if (!player) {
            return false;
        }

        try {
            let saveData = await player.save();
            await sdk.db.update('player',{id:uid},saveData);
            this.userMap.delete(uid);
            console.log(`玩家 ${uid} 被强制下线`);
            return true;
        } catch (error) {
            console.error(`强制下线玩家 ${uid} 失败:`, error);
            return false;
        }
    }
    async saveAll(){
        // 保存所有在线玩家数据
        for (const [uid, player] of this.userMap) {
            try {
                let saveData = await player.save();
                await sdk.db.update('player',{id:uid},saveData);
                
                // 同步保存用户名数据到数据库
                await this.syncUserNameToDB(uid);
            } catch (error) {
                console.error(`保存玩家 ${uid} 数据失败:`, error);
            }
        }
    }

    /**
     * 同步用户名数据到数据库
     */
    private async syncUserNameToDB(uid: string): Promise<void> {
        try {
            // 同步用户名数据
            const name = this.getNameByUid(uid);
            if (name && name !== '匿名') {
                const updateData: any = {
                    name: name,
                    updateTime: Date.now()
                };
                
                // 检查数据库中是否已存在该用户名的记录
                const existingRecord = await sdk.db.find('user_names', { uid });
                if (existingRecord.length > 0) {
                    // 更新现有记录
                    await sdk.db.update('user_names', { uid }, updateData);
                } else {
                    // 创建新记录
                    const record: UserNameRecord = {
                        uid,
                        name,
                        level: 1,
                        createTime: Date.now(),
                        updateTime: Date.now()
                    };
                    await sdk.db.insert('user_names', record);
                }
            }

        } catch (error) {
            console.error(`同步用户数据 ${uid} 到数据库失败:`, error);
        }
    }

    /**
     * 清理资源
     */
    async destroy(): Promise<void> {
        if (this.offlineCheckTask) {
            this.offlineCheckTask.stop();
            this.offlineCheckTask = null;
        }
        
        // 保存所有在线玩家数据
        await this.saveAll();
        
        // 清理用户名数据
        this.nameMap.clear();
        
        this.userMap.clear();
        this.gateMap.clear();
        this.isInitialized = false;
        this.log('info', '已销毁');
    }

    /**
     * 保存用户数据
     */
    async save(): Promise<void> {
        this.log('info', '开始保存用户数据');
        
        try {
            // 保存所有在线用户数据
            const savePromises = Array.from(this.userMap.values()).map(user => {
                return this.safeExecute(
                    () => user.save(),
                    `保存用户${user.id}数据`
                );
            });
            
            await Promise.all(savePromises);
            this.log('info', `已保存${this.userMap.size}个用户数据`);
        } catch (error) {
            this.handleError(error, '保存用户数据');
        }
    }
}

export default new UserManager();